package com.example.demoproject.camera;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

import com.example.demoproject.R;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CameraActivity<onSensorChanged> extends AppCompatActivity implements View.OnClickListener{
    private boolean isPreView = false;//是否为预览状态
    private Camera camera;
    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;
    private Button takePhotoBtn;
    private Button preViewBtn;
    SensorManager sensorManager;
    Sensor sensor;
    private int mSensorRotation = 0;
    private static int mCameraID = Camera.CameraInfo.CAMERA_FACING_BACK;//后摄

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//加速度传感器

        //设置全屏显示
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        Log.d("lfy","path="+Environment.getExternalStorageDirectory()+",state="+Environment.getExternalStorageState());
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
            Toast.makeText(this,"请安装SD卡",Toast.LENGTH_LONG).show();
        }
        //显示摄像头预览信息
        surfaceView = findViewById(R.id.surfaceView);
        surfaceHolder = surfaceView.getHolder();
        //设置surfaceView不维护缓存
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        takePhotoBtn = findViewById(R.id.takePhoto);
        preViewBtn = findViewById(R.id.preView);

        //申请动态权限，不能只在AndroidManifest.xml中声明权限，还需要申请
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 1);//1 can be another integer
        }

        takePhotoBtn.setOnClickListener(this);
        preViewBtn.setOnClickListener(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        //停止预览并释放摄像头资源
        if (camera !=null ){
            camera.stopPreview();
            camera.release();
            isPreView = false;//一定要恢复状态，不然再打开页面不会创建camera
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(new SensorEventListener() {
            @Override
            public void onSensorChanged(SensorEvent event) {
                if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                    int x = (int) event.values[0];
                    int y = (int) event.values[1];
                    int z = (int) event.values[2];
                }
                mSensorRotation = calculateSensorRotation(event.values[0],event.values[1]);
            }

            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {

            }
        },sensor,SensorManager.SENSOR_DELAY_NORMAL);
    }

    public  int calculateSensorRotation(float x, float y) {
        //x是values[0]的值，X轴方向加速度，从左侧向右侧移动，values[0]为负值；从右向左移动，values[0]为正值
        //y是values[1]的值，Y轴方向加速度，从上到下移动，values[1]为负值；从下往上移动，values[1]为正值
        //不考虑Z轴上的数据，
        if (Math.abs(x) > 6 && Math.abs(y) < 4) {//Math.abs() 返回参数的绝对值
            if (x > 6) {
                return 270;
            } else {
                return 90;
            }
        } else if (Math.abs(y) > 6 && Math.abs(x) < 4) {
            if (y > 6) {
                return 0;
            } else {
                return 180;
            }
        }
        return -1;
    }

    public  int calculatePreviewRotation() {
        //获取当前页面的rotation
        int rotation = this.getWindowManager().getDefaultDisplay().getRotation();
        Log.d("lfy","当前页面的方向："+rotation);
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }
        return degrees;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.takePhoto:
                Log.d("lfy","拍照...");
                if (camera != null){
                    camera.takePicture(null,null,takePhoto);
                }
                break;
            case R.id.preView:
                Log.d("lfy","预览...");
                Camera.CameraInfo info = new Camera.CameraInfo();
                if (!isPreView){
                    //打开摄像头
                    camera = Camera.open();
                    Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK,info);
                    Log.d("lfy","原始...info:"+info.orientation);
                    isPreView = true;
                }

                //获取预览的预览方向对应的rotation
                int result;
                if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//前摄
                    result = (info.orientation + calculatePreviewRotation()) % 360;
                    result = (360 - result) % 360;   // compensate the mirror
                } else {//后摄
                    result = ( info.orientation - calculatePreviewRotation() + 360) % 360;
                }
                Log.d("lfy","result:"+result);

                //设置预览方向
                camera.setDisplayOrientation (result);
                try {
                    //设置用于预览的surfaceView
                    camera.setPreviewDisplay(surfaceHolder);
//                    camera.setDisplayOrientation(Surface.ROTATION_90);//不能这样设置，设置的应该是0,90,270,360，而不是0,1,2,3
                    Log.d("lfy","修改后...info:"+info.orientation);
                    //获取摄像头参数
                    Camera.Parameters parameters = camera.getParameters();
                    //设置拍照后存储的图片格式
                    parameters.setPictureFormat(PixelFormat.JPEG);
                    //设置图片的分辨率，如果不设置会按默认的最低160x120分辨率拍照，拍出来的照片会非常模糊
                    parameters.setPictureSize(1920,1080);
                    parameters.set("jpeg-quality",100);
                    camera.setParameters(parameters);
                    //开始预览
                    camera.startPreview();
                    //设置自动对焦
                    camera.autoFocus(null);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
        }
    }

    public static int calculateCameraPreviewOrientation(Activity activity) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);//后摄
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;
        } else {
            result = (info.orientation - degrees + 360) % 360;
        }
        return result;
    }

    final Camera.PictureCallback takePhoto = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            Log.d("lfy","onPictureTaken......");
            Bitmap resultBitmap = null;
            if (data != null && data.length > 0) {
                //解码拍照的信息并创建位图
                Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
                //获取一个矩阵，关于矩阵的理解：
                //参考博客：https://blog.csdn.net/feather_wch/article/details/79622095
                Matrix matrix = new Matrix();
                //利用传感器获取当前屏幕方向对应角度 加上 开始预览是角度
                int rotation = (calculateCameraPreviewOrientation(CameraActivity.this) + mSensorRotation) % 360 ;
                if (mCameraID == Camera.CameraInfo.CAMERA_FACING_BACK) {
                    //如果是后置摄像头因为没有镜面效果直接旋转特定角度
                    matrix.setRotate(rotation);
                } else {
                    //如果是前置摄像头需要做镜面操作，然后对图片做镜面postScale(-1, 1)
                    //因为镜面效果需要360-rotation，才是前置摄像头真正的旋转角度
                    rotation = (360 - rotation) % 360;
                    matrix.setRotate(rotation);
                    matrix.postScale(-1, 1);
                }
                resultBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            }

            //停止预览
            camera.stopPreview();
            isPreView = false;

            //获取sd卡中照片的位置
            File appDir = new File(Environment.getExternalStorageDirectory(),"/DCIM/Camera");
            Log.d("lfy","appDir="+appDir.getAbsolutePath());
            if (!appDir.exists()){//如果目录不存在
                Log.d("lfy","onPictureTaken...文件目录不存在...");
                appDir.mkdir();//创建目录
            }

            String fileName = System.currentTimeMillis()+".jpg";
            Log.d("lfy","fileName="+fileName);
            File file = new File(appDir,fileName);
            try {
                FileOutputStream fos = new FileOutputStream(file);
                //将图片内容压缩为jpg格式输出到输出流中
                resultBitmap.compress(Bitmap.CompressFormat.JPEG,100,fos);
                fos.flush();//将缓存区中的数据全部写入到输出流中
                fos.close();//关闭文件输出流对象
            } catch (FileNotFoundException e) {
                Log.d("lfy","出错了...错误1..."+e.toString());
                e.printStackTrace();
            } catch (IOException e) {
                Log.d("lfy","出错了...错误2..."+e.toString());
                e.printStackTrace();
            }

            //将图片插入到系统图库
            try {
                MediaStore.Images.Media.insertImage(CameraActivity.this.getContentResolver(),file.getAbsolutePath(),fileName,null);
                Log.d("lfy","照片插入图库地址："+file.getAbsolutePath()+fileName);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

            //通知图库更新
            CameraActivity.this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+fileName)));
            Toast.makeText(CameraActivity.this,"图片保存至："+fileName,Toast.LENGTH_LONG).show();
            reStartPreview();//重新预览
        }
    };

    private void reStartPreview(){
        if (!isPreView){
            camera.startPreview();
            isPreView = true;
        }
    }
}
